/**
 * Copyright 2018-2020 stylefeng & fengshuonan (sn93@qq.com)
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.stylefeng.guns.config.datasource;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import cn.stylefeng.guns.core.util.CacheUtil;
import cn.stylefeng.roses.core.config.properties.DruidProperties;
import cn.stylefeng.roses.core.datascope.DataScopeInterceptor;
import cn.stylefeng.roses.core.mutidatasource.DynamicDataSource;
import cn.stylefeng.roses.core.mutidatasource.aop.MultiSourceExAop;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;

/**
 * 多数据源配置<br/>
 * <p>
 * 注：由于引入多数据源，所以让spring事务的aop要在多数据源切换aop的后面
 *
 * @author stylefeng
 * @Date 2017/5/20 21:58
 */
@Configuration
@ConditionalOnProperty(prefix = "spring.datasource", name = "muti-open", havingValue = "true")
@EnableTransactionManagement(order = 2, proxyTargetClass = true)
@MapperScan(basePackages = {"cn.stylefeng.guns.modular.*.dao", "cn.stylefeng.guns.multi.mapper"})
public class MultiDataSourceConfig {
	@Autowired
	private LyyMoreDataSourcePro lyyMoreDataSourcePro;
    /**
     * druid配置
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DruidProperties druidProperties(){ 
        return new DruidProperties();
    }

    /**
     * 多数据源配置
     */
    /*@Bean
    @ConfigurationProperties(prefix = "guns.muti-datasource")
    public MutiDataSourceProperties mutiDataSourceProperties() {
        return new MutiDataSourceProperties();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "lyy.three-datasource")
    public LyyDataSourceProperties lyyDataSourceProperties() {
        return new LyyDataSourceProperties();
    }*/

    /**
     * 多数据源切换的aop
     */
    @Bean
    public MultiSourceExAop multiSourceExAop() {
        return new MultiSourceExAop();
    }

    /**
     * guns的数据源
     */
    private DruidDataSource dataSource(DruidProperties druidProperties) {
        DruidDataSource dataSource = new DruidDataSource();
        druidProperties.config(dataSource);
        return dataSource;
    }

    /**
     * 多数据源，第二个数据源
     */
    /*private DruidDataSource bizDataSource(DruidProperties druidProperties, MutiDataSourceProperties mutiDataSourceProperties) {
        DruidDataSource dataSource = new DruidDataSource();
        druidProperties.config(dataSource);
        mutiDataSourceProperties.config(dataSource);
        return dataSource;
    }*/
    /**
     * 多数据源，第三个数据源
     */
    /*private DruidDataSource lyyDataSource(DruidProperties druidProperties, LyyDataSourceProperties lyyDataSourceProperties) {
    	DruidDataSource dataSource = new DruidDataSource();
    	druidProperties.config(dataSource);
    	lyyDataSourceProperties.config(dataSource);
    	return dataSource;
    }*/
    
   
    
    public HashMap<Object, Object> initData(HashMap<Object, Object> map,DruidProperties druidProperties,Map<String,Object> dataSourcePoint){
    	/**
         * 自动加载数据源
         */
       /* 测试代码
        * List<Map<String,String>> dataSources=lyyMoreDataSourcePro.getDataSources();
        System.out.println(dataSources.get(1).get("url"));
        druidProperties.setUrl(dataSources.get(1).get("url"));
        System.out.println(dataSources.get(2).get("username"));
        druidProperties.setUsername(dataSources.get(2).get("username"));
        System.out.println(dataSources.get(3).get("password"));
        druidProperties.setPassword(dataSources.get(3).get("password"));
    	DruidDataSource dataSourceGuns = dataSource(druidProperties);
    	 try {
             dataSourceGuns.init();
         } catch (SQLException sql) {
             sql.printStackTrace();
         }
    	 map.put(dataSources.get(0).get("dataSourceName"), dataSourceGuns);
    	return map;*/
        druidProperties.setUrl((String)dataSourcePoint.get("url"));
        druidProperties.setUsername((String)dataSourcePoint.get("username"));
        druidProperties.setPassword((String)dataSourcePoint.get("password"));
    	DruidDataSource dataSourceGuns = dataSource(druidProperties);
    	 try {
             dataSourceGuns.init();
         } catch (SQLException sql) {
             sql.printStackTrace();
         }
    	 map.put((String)dataSourcePoint.get("dataSourceName"), dataSourceGuns);
    	return map;
    }

    /**
     * 多数据源连接池配置
     */
    @Bean
//    public DynamicDataSource mutiDataSource(DruidProperties druidProperties, MutiDataSourceProperties mutiDataSourceProperties,LyyDataSourceProperties lyyDataSourceProperties) {
    public DynamicDataSource mutiDataSource(DruidProperties druidProperties){
        DruidDataSource dataSourceGuns = dataSource(druidProperties);
        /*DruidDataSource bizDataSource = bizDataSource(druidProperties, mutiDataSourceProperties);
        DruidDataSource lyyDataSource =this.lyyDataSource(druidProperties, lyyDataSourceProperties);*/
        
        

        try {
            dataSourceGuns.init();
            /*bizDataSource.init();
            lyyDataSource.init();*/
        } catch (SQLException sql) {
            sql.printStackTrace();
        }

        
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        HashMap<Object, Object> hashMap = new HashMap<>();
        hashMap.put(druidProperties.getDataSourceName(),dataSourceGuns);
        /*hashMap.put(mutiDataSourceProperties.getDataSourceNames()[1], bizDataSource);
        hashMap.put(lyyDataSourceProperties.getDataSourceNames()[1], lyyDataSource);*/
        
        /*测试无限数据源*/
        List<Map<String,String>> dataSources=lyyMoreDataSourcePro.getDataSources();
        List<Map<String,Object>> allPoint=new ArrayList<Map<String,Object>>();
        if(dataSources.size()>0){
        	
        	for(int i=0;i<dataSources.size();i++){
        		if(dataSources.get(i).containsKey("dataSourceName")){
        			if(!StringUtils.isBlank(dataSources.get(i).get("dataSourceName"))){
        				Map<String,Object> dataSourcePoint=new HashMap<String,Object>();
        				int size=i+4>dataSources.size()?dataSources.size():i+4;
        				for(int y=i+1;y<size;y++){
        					if(dataSources.get(y).containsKey("url")){
        	        			if(!StringUtils.isBlank(dataSources.get(y).get("url"))){
        	        				dataSourcePoint.put("url",dataSources.get(y).get("url"));
        	        			}
        	        		}
        					if(dataSources.get(y).containsKey("username")){
        	        			if(!StringUtils.isBlank(dataSources.get(y).get("username"))){
        	        				dataSourcePoint.put("username",dataSources.get(y).get("username"));
        	        			}
        	        		}
        					if(dataSources.get(y).containsKey("password")){
        	        			if(!StringUtils.isBlank(dataSources.get(y).get("password"))){
        	        				dataSourcePoint.put("password",dataSources.get(y).get("password"));
        	        			}
        	        		}
        					if(dataSources.get(y).containsKey("dataSourceName")){
        	        			if(!StringUtils.isBlank(dataSources.get(y).get("dataSourceName"))){
        	        				break;
        	        			}
        	        		}
        				}
        				if(dataSourcePoint.size()==3){
        					dataSourcePoint.put("dataSourceName",dataSources.get(i).get("dataSourceName"));
        					allPoint.add(dataSourcePoint);
        				}
        			}
        		}
        	}
        }
        if(allPoint.size()>0){
        	
        	for(int i=0;i<allPoint.size();i++){
        		this.initData(hashMap, druidProperties, allPoint.get(i));
        	}
        }
        
//        this.initData(hashMap, druidProperties);
        dynamicDataSource.setTargetDataSources(hashMap);
        dynamicDataSource.setDefaultTargetDataSource(dataSourceGuns);
        return dynamicDataSource;
    }
    
    
    

    /**
     * mybatis-plus分页插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /**
     * 数据范围mybatis插件
     */
    @Bean
    public DataScopeInterceptor dataScopeInterceptor() {
        return new DataScopeInterceptor();
    }

    /**
     * 乐观锁mybatis插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
